package com.yonyou.brigade.openapi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.yonyou.brigade.basic_init.model.BriChannel;
import com.yonyou.brigade.basic_init.service.IBriChannelService;
import com.yonyou.brigade.basic_init.service.IUserCenterService;
import com.yonyou.brigade.order_center.model.*;
import com.yonyou.brigade.order_center.service.*;
import com.yonyou.brigade.util.operateutil.ExcelUtils;
import com.yonyou.brigade.util.operateutil.ParameterUtils;
import com.yonyou.ybzboot.starter.common.exception.BusinessException;
import com.yonyou.ybzboot.starter.common.util.StringUtil;
import com.yonyou.ybzboot.uc.dto.UcUserDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.*;

@RequestMapping("/orderCenter")
@RestController
public class OrderController {

    private Logger logger= LoggerFactory.getLogger(OrderController.class);

    @Autowired
    @Qualifier("briFlightInfoServiceImpl")
    private IBriFlightInfoService briFlightInfoService;

    @Autowired
    @Qualifier("briHotelRoomServiceImpl")
    private IBriHotelRoomService briHotelRoomService;

    @Autowired
    @Qualifier("briTrainTicketServiceImpl")
    private IBriTrainTicketService briTrainTicketService;

    @Autowired
    @Qualifier("briCarOrderServiceImpl")
    private IBriCarOrderService briCarOrderService;

    @Autowired
    @Qualifier("briOrderServiceImpl")
    private IBriOrderService briOrderService;

    @Autowired
    private IUserCenterService userCenterService;

    @Autowired
    private IBriChannelService briChannelService;

    @RequestMapping(value = "/query/getOrdersByOrderNoAndClass",method = RequestMethod.POST)
    public @ResponseBody
    List<BriOrderListVO> getOrdersByOrderNoAndClass(@RequestBody JSONArray params) {
        logger.info("通过订单编号和订单类别查询订单的参数：" + JSON.toJSONString(params));
        List<BriOrderListVO> briOrderListVOS = briOrderService.getOrdersByOrderNoAndClass(params);
        return briOrderListVOS;
    }

    /**
     * 根据时间范围查询订单
     * @param tenantId
     * @param params
     * @return
     */
    @RequestMapping(value = "/query/getOrdersByTimeRange",method = RequestMethod.POST)
    public @ResponseBody
    JSONObject getOrdersByTimeRange(String tenantId, @RequestBody JSONObject params)
    {
        logger.info("通过时间范围查询订单的参数：" + JSON.toJSONString(params));
        JSONObject ordersByTimeRange = briOrderService.getOrdersByTimeRange(tenantId, params);
        logger.info("通过时间范围查询订单的返回：" + JSON.toJSONString(ordersByTimeRange));
        return ordersByTimeRange;
    }

    /**
     * 根据申请单号查询订单
     * @param tenantId
     * @param params
     * @return
     */
    @RequestMapping(value = "/query/getOrdersByApplyIds",method = RequestMethod.POST)
    public @ResponseBody
    JSONObject getOrdersByApplyIds(String tenantId, @RequestBody JSONObject params)
    {
        logger.info("通过申请单号查询订单的参数：" + JSON.toJSONString(params));
        JSONObject ordersByApplyIds = briOrderService.getOrdersByApplyIds(tenantId, params);
        logger.info("通过申请单号查询订单的返回：" + JSON.toJSONString(ordersByApplyIds));
        return ordersByApplyIds;
    }

    /**
     * 第三方推送订单数据到订单中心
     * @param params
     * @param token
     * @return
     */
    @RequestMapping(value = "/save/orderInfos", method = RequestMethod.POST)
    public String saveOrderInfos(@RequestBody JSONObject params, String token) {
        logger.info("第三方推送的数据为" + JSON.toJSONString(params));
        if (StringUtils.isEmpty(token)) {
            throw new BusinessException("token不能为空");
        }
        if (com.yonyou.brigade.util.operateutil.StringUtils.generateJudgment(token)) {
            throw new BusinessException("token验证不通过");
        }
        JSONArray flightOrders = params.getJSONArray("flightOrders");
        JSONArray hotelOrders = params.getJSONArray("hotelOrders");
        JSONArray trainOrders = params.getJSONArray("trainOrders");
        JSONArray carOrders = params.getJSONArray("carOrders");
        if (CollectionUtils.isEmpty(flightOrders) && CollectionUtils.isEmpty(hotelOrders) && CollectionUtils.isEmpty(trainOrders) && CollectionUtils.isEmpty(carOrders)) {
            return "未获取到订单信息，请检查参数";
        }
        //保存机票订单
        if (flightOrders != null && flightOrders.size() > 0) {
            for (int i = 0; i < flightOrders.size(); i++) {
                try {
                    JSONObject orderJson = flightOrders.getJSONObject(i);
                    String orderNo = orderJson.getString("orderNo");
                    String personCodeOrPhone = orderJson.getString("userId");
                    if (!StringUtils.isEmpty(orderJson.getString("signForTenant"))) {
                        List<BriChannel> briChannels = getBriChannelsBySignForTenant(orderJson);
                        if (!CollectionUtils.isEmpty(briChannels)) {
                            BriChannel briChannel = briChannels.get(0);
                            briOrderService.saveFlight(orderJson, orderNo, briChannel.getTenant(), personCodeOrPhone, briChannel.getChannel(), briChannel.getId());
                        } else {
                            throw new BusinessException("请检查保存机票订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                        }
                    } else {
                        throw new BusinessException("请检查保存机票订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                    }
                } catch (Exception e) {
                    throw new BusinessException("保存机票订单时出现错误，具体信息：" + e.getMessage());
                }
            }
        }
        //保存酒店订单
        if (hotelOrders != null && hotelOrders.size() > 0) {
            for (int i = 0; i < hotelOrders.size(); i++) {
                try {
                    JSONObject orderJson = hotelOrders.getJSONObject(i);
                    String orderNo = orderJson.getString("orderNo");
                    String personCodeOrPhone = orderJson.getString("userId");
                    if (!StringUtils.isEmpty(orderJson.getString("signForTenant"))) {
                        List<BriChannel> briChannels = getBriChannelsBySignForTenant(orderJson);
                        if (!CollectionUtils.isEmpty(briChannels)) {
                            BriChannel briChannel = briChannels.get(0);
                            briOrderService.saveHotel(orderJson, orderNo, briChannel.getTenant(), personCodeOrPhone, briChannel.getChannel(),briChannel.getId());
                        } else {
                            throw new BusinessException("请检查保存酒店订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                        }
                    } else {
                        throw new BusinessException("请检查保存酒店订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                    }
                } catch (Exception e) {
                    throw new BusinessException("保存酒店订单时出现错误，具体信息：" + e.getMessage());
                }
            }
        }
        //保存火车票订单
        if (trainOrders != null && trainOrders.size() > 0) {
            for (int i = 0; i < trainOrders.size(); i++) {
                try {
                    JSONObject orderJson = trainOrders.getJSONObject(i);
                    String orderNo = orderJson.getString("orderNo");
                    String personCodeOrPhone = orderJson.getString("userId");
                    List<BriChannel> briChannels = getBriChannelsBySignForTenant(orderJson);
                    if (!StringUtils.isEmpty(orderJson.getString("signForTenant"))) {
                        if (!CollectionUtils.isEmpty(briChannels)) {
                            BriChannel briChannel = briChannels.get(0);
                            briOrderService.saveTrain(orderJson, orderNo, briChannel.getTenant(), personCodeOrPhone, briChannel.getChannel(),briChannel.getId());
                        } else {
                            throw new BusinessException("请检查保存火车票订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                        }
                    } else {
                        throw new BusinessException("请检查保存火车票订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                    }
                } catch (Exception e) {
                    throw new BusinessException("保存火车订单时出现错误，具体信息：" + e.getMessage());
                }
            }
        }
        //保存用车订单
        if (carOrders != null && carOrders.size() > 0) {
            for (int i = 0; i < carOrders.size(); i++) {
                try {
                    JSONObject orderJson = carOrders.getJSONObject(i);
                    String orderNo = orderJson.getString("orderNo");
                    String personCodeOrPhone = orderJson.getString("userId");
                    if (!StringUtils.isEmpty(orderJson.getString("signForTenant"))) {
                        List<BriChannel> briChannels = getBriChannelsBySignForTenant(orderJson);
                        if (!CollectionUtils.isEmpty(briChannels)) {
                            BriChannel briChannel = briChannels.get(0);
                            briOrderService.saveCar(orderJson, orderNo, briChannel.getTenant(), personCodeOrPhone, briChannel.getChannel(),briChannel.getId());
                        } else {
                            throw new BusinessException("请检查保存用车订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                        }
                    } else {
                        throw new BusinessException("请检查保存用车订单时的signForTenant："+ orderJson.getString("signForTenant") + "是否正确！");
                    }
                } catch (Exception e) {
                    throw new BusinessException("保存用车订单时出现错误，具体信息：" + e.getMessage());
                }
            }
        }
        return "订单保存成功";
    }

    private List<BriChannel> getBriChannelsBySignForTenant(JSONObject orderJson) {
        String signForTenant = orderJson.getString("signForTenant");
        Wrapper<BriChannel> briChannelWrapper = new EntityWrapper<>();
        briChannelWrapper.where("sign_for_tenant={0}", signForTenant);
        briChannelWrapper.andNew("enable={0}", 1);
        return briChannelService.selectList(briChannelWrapper);
    }

    /**
     * 订单中心的查询
     * @param params
     * @return
     */
    @RequestMapping(value = "/query/orderInfos", method = RequestMethod.POST)
    public Map getOrderInfos(@RequestBody Map params) {
        Map result = new HashMap();
        String type = params.get("type").toString();
        if ("flight".equals(type)) {
            result = briFlightInfoService.getBriFlightInfoDTOs(params);
        } else if ("hotel".equals(type)) {
            result = briHotelRoomService.getBriHotelRoomDTOs(params);
        } else if ("train".equals(type)) {
            result = briTrainTicketService.getBriTrainTicketDTOs(params);
        } else if ("car".equals(type)) {
            result = briCarOrderService.getBriCarOrderDTOs(params);
        } else {
            result.put("code", "0");
            result.put("information", null);
        }
        return result;
    }

    /**
     * 订单中心下拉列表的查询
     * @param params
     * @return
     */
    @RequestMapping(value = "/menuOptions", method = RequestMethod.POST)
    public Map getMenuOptions(@RequestBody Map params) {
        Map result = briOrderService.getMenuOptions(params);
        return result;
    }

    /**
     * 订单中心的数据导出
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/export/exportOrders", method = RequestMethod.GET)
    public Map exportOrder (HttpServletRequest request, HttpServletResponse response) {
        Map result = new HashMap();
        try {
            request.setCharacterEncoding("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Map<String, Object> parameterMap = ParameterUtils.getParameterMap(request);
        parameterMap.put("pageSize", 10000);
        parameterMap.put("current", 1);
        String type = (String) parameterMap.get("type");
        if ("flight".equals(type)) {
            Map exportResult = briFlightInfoService.getBriFlightInfoDTOs(parameterMap);
            if (exportResult != null && exportResult.get("code").equals("0")) {
                List<BriFlightInfoDTO> flightInfoDTOS = new ArrayList<>();
                flightInfoDTOS = JSON.parseArray(JSON.toJSONString(exportResult.get("information")), BriFlightInfoDTO.class);
                List<String> headersList = new ArrayList<>();
                if (parameterMap.get("excelData") != null) {
                    headersList = JSONArray.parseObject(parameterMap.get("excelData").toString(), ArrayList.class);
                }
                String[] headers = new String[headersList.size()];
                headersList.toArray(headers);
                String[] exportFileds = headers;
                ExcelUtils.doExportExcelBySomeFiled("商旅订单", "机票订单", headers, flightInfoDTOS, null, response, null, exportFileds);
            }
        } else if ("hotel".equals(type)) {
            Map exportResult = briHotelRoomService.getBriHotelRoomDTOs(parameterMap);
            if (exportResult != null && exportResult.get("code").equals("0")) {
                List<BriHotelRoomDTO> hotelRoomDTOs = new ArrayList<>();
                hotelRoomDTOs = JSON.parseArray(JSON.toJSONString(exportResult.get("information")), BriHotelRoomDTO.class);
                List<String> headersList = new ArrayList<>();
                if (parameterMap.get("excelData") != null) {
                    headersList = JSONArray.parseObject(parameterMap.get("excelData").toString(), ArrayList.class);
                }
                String[] headers = new String[headersList.size()];
                headersList.toArray(headers);
                String[] exportFileds = headers;
                ExcelUtils.doExportExcelBySomeFiled("商旅订单", "酒店订单", headers, hotelRoomDTOs, null, response, null, exportFileds);
            }
        } else if ("train".equals(type)) {
            Map exportResult = briTrainTicketService.getBriTrainTicketDTOs(parameterMap);
            if (exportResult != null && exportResult.get("code").equals("0")) {
                List<BriTrainTicketDTO> trainTicketDTOs = new ArrayList<>();
                trainTicketDTOs = JSON.parseArray(JSON.toJSONString(exportResult.get("information")), BriTrainTicketDTO.class);
                List<String> headersList = new ArrayList<>();
                if (parameterMap.get("excelData") != null) {
                    headersList = JSONArray.parseObject(parameterMap.get("excelData").toString(), ArrayList.class);
                }
                String[] headers = new String[headersList.size()];
                headersList.toArray(headers);
                String[] exportFileds = headers;
                ExcelUtils.doExportExcelBySomeFiled("商旅订单", "火车票订单", headers, trainTicketDTOs, null, response, null, exportFileds);
            }
        } else if ("car".equals(type)) {
            Map exportResult = briCarOrderService.getBriCarOrderDTOs(parameterMap);
            if (exportResult != null && exportResult.get("code").equals("0")) {
                List<BriCarOrderDTO> carOrderDTOs = new ArrayList<>();
                carOrderDTOs = JSON.parseArray(JSON.toJSONString(exportResult.get("information")), BriCarOrderDTO.class);
                List<String> headersList = new ArrayList<>();
                if (parameterMap.get("excelData") != null) {
                    headersList = JSONArray.parseObject(parameterMap.get("excelData").toString(), ArrayList.class);
                }
                String[] headers = new String[headersList.size()];
                headersList.toArray(headers);
                String[] exportFileds = headers;
                ExcelUtils.doExportExcelBySomeFiled("商旅订单", "用车订单", headers, carOrderDTOs, null, response, null, exportFileds);
            }
        }
        result.put("code", "0");
        result.put("information", "操作成功");
        return result;
    }


    @RequestMapping(value = "/query/getOrdersByBxState")
    public Map getOrdersByBxState(String clientId, String tenantId, String phone, String token, String third, @RequestBody JSONObject queryParam){
        if (StringUtil.isEmpty(clientId) || StringUtil.isEmpty(tenantId)) {
            throw new BusinessException("验证失败");
        }
        UcUserDto user = userCenterService.getCompleteUcUserDtoByPhone(phone, tenantId);
        if (user == null){
            throw new BusinessException("无效用户");
        }
        String userId = user.getUserId();
        String beginDate = queryParam.getString("beginDate");
        String endDate = queryParam.getString("endDate");
        String bxState = queryParam.getString("bxState");
        JSONObject orders = briOrderService.getOrders(userId, bxState, beginDate, endDate, "", tenantId);
        return orders;
    }

    @RequestMapping(value = "/query/getOrdersByNo", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject getOrdersByNo(String clientId, String tenantId, String phone, String token, String third, @RequestBody JSONArray paramArr){
        if (StringUtil.isEmpty(clientId) || StringUtil.isEmpty(tenantId)) {
            throw new BusinessException("验证失败");
        }
        JSONObject result = new JSONObject();
        JSONArray flightOrders = new JSONArray();
        JSONArray carOrders = new JSONArray();
        JSONArray hotelOrders = new JSONArray();
        JSONArray trainOrders = new JSONArray();
        Set<String> orderNoSet = new HashSet<>();
        for (int i = 0; i < paramArr.size(); i++) {
            JSONObject param = paramArr.getJSONObject(i);
            String orderNo = param.getString("orderNo");
            String type = param.getString("type");
            if (orderNoSet.contains(orderNo)){
                continue;
            }
            JSONArray orders = briOrderService.getOrders(tenantId, type, orderNo);
            for (int j = 0; j < orders.size(); j++) {
                orderNoSet.add(orders.getJSONObject(j).getString("orderNo"));
            }
            if (orders != null && orders.size() > 0){
                switch (type){
                    case "flight":
                        flightOrders.addAll(orders);
                        break;
                    case "car":
                        carOrders.addAll(orders);
                        break;
                    case "train":
                        trainOrders.addAll(orders);
                        break;
                    case "hotel":
                        hotelOrders.addAll(orders);
                        break;
                }
            }
        }
        result.put("flightOrders", flightOrders);
        result.put("trainOrders", trainOrders);
        result.put("carOrders", carOrders);
        result.put("hotelOrders", hotelOrders);
        return result;
    }

    private String[] carWrapperHeaderNames() {
        String headerNamesStr = "orderNo,fromType,type,publicOrPrivate,isDomc,orderStatus,vehicleModel,startName,endName,departureTime,arriveTime,callPhone,psgName,psgPhone,linkerName,linkerPhone,driverPhone,vehicleCard,createBy,payType,paymentType,cityName,distance,duration,totalPrice,actualPrice,inApproveId,employeeNumber,useCarSrv,bxState,category,otherInfo,assumeOrg,assumeDept,costProject,applyUser,companion";
        String[] headerNames = headerNamesStr.split(",");
        return headerNames;
    }

    private String[] carWrapperHeaders() {
        String headerFiledsStr = "订单号,订单来源,订单类型,因公因私,国内国际类型,订单状态,车型,出发地,目的地,出发时间,到达时间,叫车人手机号,乘客姓名,乘客手机号,联系人姓名,联系人手机号,司机手机号,车牌号,创建人,支付类型,支付方式,城市名称,本单里程,本单时长,总费用,实付金额,我方审批单单号,员工工号,用车类型,报销状态,商旅标记,备注,费用承担单位,费用承担部门,费用项目,实际申请人,实际出行人";
        String[] headerFileds = headerFiledsStr.split(",");
        return headerFileds;
    }

    private String[] flightWrapperHeaders() {
        String headerFiledsStr = "订单来源,订单类型,原单号,订单号,预定人,员工编号,乘机人,乘机人职级,航班类型,航程,航空公司,航班号,舱位级别,最低价,全价,折扣,票面价,基建+燃油,保险,送票费,服务费,绑定服务费,改签费,退票费,结算币种,实付金额,支付方式,预定方式,机票类型,提前预定天数,预定时间,起飞时间,到达时间,未提前预定原因,未预定最低价原因,溢价预定原因,部门1,部门2,部门3,成本中心1,成本中心2,成本中心3,关联行程,关联申请号,授权状态,报销状态,备注,自定义字段1,自定义字段2,自定义字段3,自定义字段4,自定义字段5,费用承担单位,费用承担部门,费用项目,实际申请人,实际出行人";
        String[] headerFileds = headerFiledsStr.split(",");
        return headerFileds;
    }

    private String[] flightWrapperHeaderNames() {
        String headerNamesStr = "fromType,orderType,OldOrderNo,orderNo,createBy,oaUserCode,psgName,psgLevel,isDomc,flightWay,carrierName,flightNO,classLevelName,lowestPrice,yPrice,classRebate,farePrice,consturctAndFuel,sumInsMoney,sendTicketFee,counterFee,bindCounterFee,changeFee,tpPrice,currency,paymentPrice,payType,preOrderMode,psgType,preDays,orderTime,flightDateTime,flightEndDateTime,noPreOrderReason,noOrderLowstReason,premiumReason,department1,department2,department3,costCenter1,costCenter2,costCenter3,relateYBZID,relateOtherID,authStatus,bxStatus,note,defItem1,defItem2,defItem3,defItem4,defItem5,,assumeOrg,assumeDept,costProject,applyUser,companion";
        String[] headerNames = headerNamesStr.split(",");
        return headerNames;
    }

    private String[] hotelWrapperHeaders() {
        String headerFiledsStr = "预定来源,订单号,预定人,员工编号,订单状态,入住人,住宿标准,预定日期,入住日期,离店日期,入住城市,酒店名称,房型,房间数,入住天数,间夜,服务费,结算币种,实付金额,支付方式,预订方式,超标原因,部门1,部门2,部门3,成本中心1,成本中心2,成本中心3,关联行程号,关联申请单号,授权状态,报销状态,备注,自定义字段1,自定义字段2,自定义字段3,自定义字段4,自定义字段5,费用承担单位,费用承担部门,费用项目,实际申请人,实际出行人";
        String[] headerFileds = headerFiledsStr.split(",");
        return headerFileds;
    }

    private String[] hotelWrapperHeaderNames() {
        String headerNamesStr = "fromType,orderNO,createBy,OAUserCode,orderStatus,psgName,hotelLevel,createTime,arrivalDate,departureDate,hotelCity,hotelName,roomName,roomNums,inDays,inNights,serviceFee,currency,paymentPrice,paymentType,preOrderMode,preiumReason,department1,department2,department3,costCenter,costCenter2,costCenter3,relateYBZID,relateOtherID,authStatus,bxStatus,note,defItem1,defItem2,defItem3,defItem4,defItem5,assumeOrg,assumeDept,costProject,applyUser,companion";
        String[] headerNames = headerNamesStr.split(",");
        return headerNames;
    }

    private String[] trainWrapperHeaders() {
        String headerFiledsStr = "预定来源,订单类型,原单号,订单号,预订人,员工编号,乘车人,乘车人职级,车次,席别,预定日期,发车时间,到站时间,出发站,到达站,票面价,服务费,保险费,送票费,改签费,退票费,结算币种,实付金额,支付方式,预订方式,超标原因,部门1,部门2,部门3,成本中心1,成本中心2,成本中心3,关联行程号,关联申请单号,授权状态,报销状态,备注,自定义字段1,自定义字段2,自定义字段3,自定义字段4,自定义字段5,费用承担单位,费用承担部门,费用项目,实际申请人,实际出行人";
        String[] headerFileds = headerFiledsStr.split(",");
        return headerFileds;
    }

    private String[] trainWrapperHeaderNames() {
        String headerNamesStr = "fromType,orderType,parentOrderNo,orderNo,createBy,oaUserCode,psgName,psgPosition,trainCode,seatType,orderTime,fromDateTime,toDateTime,fromStation,toStation,tktPrice,counterFee,sumInsMoney,sendTicketFee,carrierChangeFee,tpPrice,currency,paymentPrice,paymentType,preOrderMode,preiumReason,department1,department2,department3,costCenter,costCenter2,costCenter3,relateYBZID,relateOtherID,authStatus,bxStatus,note,defItem1,defItem2,defItem3,defItem4,defItem5,assumeOrg,assumeDept,costProject,applyUser,companion";
        String[] headerNames = headerNamesStr.split(",");
        return headerNames;
    }

}
